package com.example.seed.config.security;

import com.example.seed.entity.CacheConstant;
import com.example.seed.entity.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.*;

@Component
public class TokenService {

    @Resource
    private RedissonClient redissonClient;

    public LoginUser getLoginUser(HttpServletRequest request) {
        String token = parseToken(request);
        return getLoginUser(token);
    }


    private LoginUser getLoginUser(String token) {
        RBucket<LoginUser> bucket = redissonClient.getBucket(CacheConstant.LOGIN_TOKEN_KEY + token);
        return bucket.get();
    }

    public String getToken(LoginUser loginUser) {
        String token = UUID.randomUUID().toString();

        // 缓存30分钟
        RBucket<LoginUser> bucket = redissonClient.getBucket(CacheConstant.LOGIN_TOKEN_KEY + token);
        bucket.set(loginUser, Duration.ofMinutes(30));

        Map<String, Object> claims = new HashMap<>();
        claims.put(CacheConstant.TOKEN, token);
        return createToken(claims);
    }

    private String createToken(Map<String, Object> claims) {
        Date date = new Date();
        Date expireTime = new Date(date.getTime() + 30 * 60 * 1000);
        return Jwts.builder().claims(claims).signWith(KeyProvider.getKey()).expiration(expireTime).compact();
    }

    private String parseToken(HttpServletRequest request) {
        try {
            String token = request.getHeader(CacheConstant.HEADER);
            if (Objects.nonNull(token) && token.startsWith(CacheConstant.TOKEN_PREFIX)) {
                token = token.replace(CacheConstant.TOKEN_PREFIX, "");
            }
            JwtParser build = Jwts.parser().verifyWith(KeyProvider.getKey()).build();
            Jws<Claims> claimsJws = build.parseSignedClaims(token);
            Claims payload = claimsJws.getPayload();
            return payload.get(CacheConstant.TOKEN, String.class);
        } catch (Exception e) {
            throw new RuntimeException("token验证失败");
        }
    }

    public boolean logout(HttpServletRequest request) {
        String token = parseToken(request);
        RBucket<LoginUser> bucket = redissonClient.getBucket(CacheConstant.LOGIN_TOKEN_KEY + token);
        return bucket.delete();
    }
}
